package com.jdz.noise.tools;

import com.jdz.noise.entities.GPS;
import com.jdz.noise.entities.FlyRow;
import com.jdz.noise.entities.NoiseRow;
import com.jdz.noise.entities.Point;
import net.sf.json.JSONArray;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static com.jdz.noise.tools.ControlUtil.*;

public class SphereAlg {

    public static Object[] X;//存储球面座标
    public static Object[] Z;//存储球面座标
    public static Object[] SPL;//存储升压值


    /**
     * 将WGS-84坐标转化为笛卡尔系坐标（空间系坐标）
     *
     * @param gps
     * @return double[3];
     * 空间坐标系坐标（x，y，z）;
     * 0 : x;
     * 1 : y;
     * 2 : z;
     */


    public static double[] transGpsToCartesian(GPS gps) {////输入gps
        double[] gpsArray = gps.toArray();
        double latitude = gpsArray[0];
        double longitude = gpsArray[1];
        double altitude = gpsArray[2];

        double[] xyz = new double[3];//需要返回的笛卡尔坐标数组
        double a = 6378137;//地球椭球长半轴，单位m
        double f = 1.0 / 298.257223565;//椭球体的极扁率
        double b = a * (1.0 - f);//地球椭球短半轴
        //double e2 = 1 - (b * b) / (a * a);//椭球偏心率的平方
        double N = a / Math.sqrt(1.0 - f * (2.0 - f) * Math.pow(Math.sin(latitude), 2));//N为基准椭球体的曲率半径
        xyz[0] = (N + altitude) * Math.cos(latitude) * Math.cos(longitude);//转化后x轴坐标
        xyz[1] = (N + altitude) * Math.cos(latitude) * Math.sin(longitude);//转化后y轴坐标
        xyz[2] = (N * Math.pow((1 - f), 2) + altitude) * Math.sin(latitude);//转化后z轴坐标
        return xyz;
    }

    //输入两点的笛卡尔坐标系，取得交点相对于飞机的位置
    public static double[] getCorner(double[] air, double[] ground)//输入两点的笛卡尔坐标系
    {

        double[] res = new double[2];//double【0】与x轴的夹角，double[1】与Z轴的夹角
        double cornerX;
        double cornerZ;
        double differX = ground[0] - air[0];//x差
        double differY = ground[1] - air[1];//y差
        double differZ = ground[2] - air[2];//Z差

        cornerX = Math.toDegrees(Math.atan(differY / differX));
        cornerZ = Math.toDegrees(Math.atan(-differZ / 1.0));//这样是以水平面为0度，differZ前不加负号就是以Z轴正方向为0度

        res[0] = cornerX;
        res[1] = cornerZ;

        return res;
    }

    //获得声压值,以距离比作噪声比，目前R选用1m
    public static double getSpl(GPS groundGPS, GPS airGps, double oriSpl)//输入统一坐标后的gps坐标
    {
        double spl = 0;
        double dis_proportion = 1 / Interpolation.distance(groundGPS, airGps);
        spl = oriSpl * dis_proportion;
        return Math.abs(spl);
    }


    //遍历生成轨迹弧线

    /**
     * @return
     */
    //遍历生成轨迹弧线
    public static Map<String, ArrayList<Point>> arc() {
        Map<String, ArrayList<Point>> track_arc = new HashMap<String, ArrayList<Point>>();

        //地面gps
        double[][] array_gps = {
                {29, 1, 0, 117, 0, 0, 244.118},
                {29, 5, 0, 117, 0, 0, 244.118},
                {29, 10, 0, 117, 0, 0, 244.118}
        };
        //获取声道数
        int track = 3;

        //存放数据
        List x = new ArrayList();
        List z = new ArrayList();
        List spl = new ArrayList();

        GPS[] groundGps = new GPS[track];
        for (int i = 0; i < track; i++) {
            groundGps[i] = new GPS(array_gps[i]);
        }
        //遍历时间同步后的数据
        //{
        //      这一层遍历各个声道,摘出参数: 地面坐标，声压值（本声道），飞机gps
        //}
        ArrayList<Point> lp[] = new ArrayList[track];
        for (int i = 0; i < track; i++) {
            groundGps[i] = new GPS(array_gps[i]);

            lp[i] = new ArrayList();
        }
        for (NoiseRow noiseRow : noise_fly.keySet()) {
            for (int i = 0; i < track; i++) {

                double oriSpl = noiseRow.getVocal_tract().get(i);//获取第i个声道的噪声值
                FlyRow flyRow = noise_fly.get(noiseRow);
                GPS air_gps = new GPS(flyRow);//获取飞机此时的gps
                //然后，先拿点，后拿值
                if(oriSpl != 0) {
                    Point point = getPoint(groundGps[i], air_gps, oriSpl);
                    System.out.println(point.toString());
                    x.add(point.getCornerX());
                    z.add(point.getCornerZ());
                    spl.add(point.getSpl());
                    lp[i].add(point);
                }
            }
        }
        X = x.toArray();
        Z = z.toArray();
        SPL = spl.toArray();
        for (int i = 0; i < track; i++) {
            track_arc.put("track" + i, lp[i]);
        }
        return track_arc;
    }


    public static Point getPoint(GPS groundGps, GPS airGps, double oriSpl) {
        //转笛卡尔坐标         transGpsToCartesian
        //获取角度             getCorner
        //获取声压值            getSpl
        //生成Point             point.set   cornerX、cornerZ、spl
        double[] ground = transGpsToCartesian(groundGps);
        double[] air = transGpsToCartesian(airGps);
        double[] corner = getCorner(ground, air);
        double spl = getSpl(groundGps, airGps, oriSpl);
        Point point = new Point(corner[0], corner[1], spl);
        return point;
    }

    //如何调用
    public static String getSphereAlg() throws InterruptedException {
        /*        gps_ground!=null && trackNum != 0*/
        if (true) {
//          arc();
//

            Object data_train[][] = new Object[3][];
            data_train[0] = SPL;
            data_train[1] = X;
            data_train[2] = Z;

            String res_data_train = JSONArray.fromObject(data_train).toString();
            Thread.sleep(2000);
            return "{\"msg\":\"success\"}";
           // return "{\"msg\":\"success\",\"data\":" + res_data_train + "}";
        } else {

            return "{\"msg\":\"构建声学球失败\"}";

        }
    }



}
